#include "tb_cxxrtl_io.h"
#include "xoroshiro.h"
#include "amo_outline.h"

#include <stdint.h>

// Push some pseudorandom data through each of the supported AMO operations,
// to make sure the AMO ALU behaviour is plausibly correct.

#define N_REPS_OUTER 10
#define N_REPS_INNER 10

typedef uint32_t (*amofunc)(uint32_t val, uint32_t *addr);

static const struct {const char *name; amofunc f;} amo_funcs[] = {
	{"amoswap.w", amoswap},
	{"amoadd.w",  amoadd },
	{"amoxor.w",  amoxor },
	{"amoand.w",  amoand },
	{"amoor.w",   amoor  },
	{"amomin.w",  amomin },
	{"amomax.w",  amomax },
	{"amominu.w", amominu},
	{"amomaxu.w", amomaxu},
};

int main() {
	// Nothing up my sleeve :)
	uint64_t rand_state[4] = {
		0xb1946ac92492d234ull, 0x7c6235b4d2611184ull,
		0x591785b794601e21ull, 0x2b260e25925636fdull
	};

	// The reason for the outer loop is that some operations (e.g. OR)
	// converge on a stationary point with repeated application, so we run
	// multiple sequences with random initial values to make sure we don't
	// miss anything.

	uint32_t scratch;
	for (int i = 0; i < N_REPS_OUTER; ++i) {
		for (int j = 0; j < sizeof(amo_funcs) / sizeof(*amo_funcs); ++j) {
			tb_puts(amo_funcs[j].name);
			tb_puts("\n");
			scratch = (uint32_t)xr256_next(rand_state);
			for (int k = 0; k < N_REPS_INNER; ++k) {
				tb_put_u32(amo_funcs[j].f((uint32_t)xr256_next(rand_state), &scratch));
			}
		}
	}
}

/*EXPECTED-OUTPUT***************************************************************

amoswap.w
bd812f70
0e8bd50b
4caec9a1
dec51bd3
d9bc590b
93beae3c
947c9e82
f1a84e3c
4c252aed
0de03b6c
amoadd.w
3ef16d93
5f126960
0159f703
f598e50c
c544c086
bc4c0994
6911b251
12c8d490
def7065a
073d16ac
amoxor.w
9be80cd9
b8d562c1
ea86a2b7
eb57c10a
e32815a7
aa147a23
b2924d3f
c2a6ea1c
b53b0d82
c9d848a9
amoand.w
4c127d18
4c020c00
08000c00
00000c00
00000c00
00000800
00000000
00000000
00000000
00000000
amoor.w
da625fdd
dbefdfff
ffffffff
ffffffff
ffffffff
ffffffff
ffffffff
ffffffff
ffffffff
ffffffff
amomin.w
a5fa4558
a5fa4558
976f5485
976f5485
976f5485
976f5485
91fc40a0
91fc40a0
91fc40a0
91fc40a0
amomax.w
4e6b9ee1
4e6b9ee1
6148d7b1
6148d7b1
6148d7b1
6148d7b1
6148d7b1
6148d7b1
6148d7b1
6148d7b1
amominu.w
e52ee072
901087c0
7d6e1835
648508d5
648508d5
648508d5
12a55566
12a55566
12a55566
12a55566
amomaxu.w
300f6b09
300f6b09
cd6dbc33
cd6dbc33
cd6dbc33
cd6dbc33
cd6dbc33
cd6dbc33
cd6dbc33
f8c6aaff
amoswap.w
3c04b397
db284cc7
d191ea23
1ddd8edc
970635f9
443afbfb
9d945e61
6427b3f3
d13329da
b779400a
amoadd.w
d424dc87
8cc722bb
c810eb2c
0c1b28bc
2f6fbdf7
6f83d685
6b797f4e
9edb8d47
00280cd8
b0ef42f9
amoxor.w
ab7aec2e
5db22fed
55b56011
d7ca6154
e22d00b6
a3a135e4
39f871a1
3502c0dc
f1139621
66553cf3
amoand.w
ecf1125e
6420024c
4420004c
40200000
00000000
00000000
00000000
00000000
00000000
00000000
amoor.w
deeb28c5
deff2cdf
dfffefdf
ffffffdf
ffffffdf
ffffffff
ffffffff
ffffffff
ffffffff
ffffffff
amomin.w
11ede889
ff20a14c
df5a7715
df5a7715
867b7905
867b7905
867b7905
867b7905
867b7905
867b7905
amomax.w
729eb6f7
729eb6f7
729eb6f7
729eb6f7
729eb6f7
729eb6f7
729eb6f7
729eb6f7
729eb6f7
729eb6f7
amominu.w
a5c76b54
89a17764
89a17764
86457986
86457986
717e2b66
717e2b66
01544967
01544967
01544967
amomaxu.w
8e1d1573
9351e093
d3d99342
d3d99342
d3d99342
d3d99342
d3d99342
d3d99342
d3d99342
d3d99342
amoswap.w
244a1ab9
6bc0c9ef
51bc17f8
446f8373
4d3ec1d7
b2745469
4628ebd1
badb618d
d0c9be37
41f0bb30
amoadd.w
31bfc66b
e9b30cdf
e7169a61
e2b6d0ce
08f67e21
f75879a3
50889813
357d9022
76a62838
a20e764e
amoxor.w
51dc5e2e
d787d9a6
42c1f8d7
1d87debf
8ff94cdc
aeac2620
936f534a
7f7da722
9469c92e
73b7e0ef
amoand.w
0b45c4d1
01048090
00008090
00000080
00000080
00000080
00000080
00000080
00000080
00000000
amoor.w
bad1e6c4
ffd7f7e6
fff7fff6
fffffff6
fffffff6
ffffffff
ffffffff
ffffffff
ffffffff
ffffffff
amomin.w
131b6e41
131b6e41
afef5e07
9cf0e84e
9cf0e84e
9cf0e84e
9cf0e84e
9cf0e84e
9cf0e84e
9cf0e84e
amomax.w
0a3a89f4
0a3a89f4
0a3a89f4
0a3a89f4
24974e5d
64efcdd5
64efcdd5
64efcdd5
64efcdd5
64efcdd5
amominu.w
c927bb2f
aefcd7ef
4d2cdc2f
4d2cdc2f
4d2cdc2f
1fe2d851
1fe2d851
1fe2d851
1fe2d851
1fe2d851
amomaxu.w
3f39c061
e76ee82b
e76ee82b
e76ee82b
e76ee82b
e76ee82b
e76ee82b
e76ee82b
e76ee82b
e8ab0f85
amoswap.w
9687c71e
362d72e1
6048673d
2128cde8
37eb8ca5
a00c0ba5
25407636
dc2d5532
0d6bdaab
074e55a0
amoadd.w
4ccb584d
23db0856
67581f65
d9e7f6e8
d4d51803
0c0258c8
758986cd
05cb0976
43a9794b
718194a7
amoxor.w
51608a5c
a19c4090
cfa55b04
bdcd610c
26480837
80ff9c99
e8860dd1
16fe2301
887a1110
84ac1069
amoand.w
24644d19
00400d01
00000900
00000800
00000800
00000000
00000000
00000000
00000000
00000000
amoor.w
43d40078
dbf508fe
dbf7ccff
ffffccff
ffffefff
ffffffff
ffffffff
ffffffff
ffffffff
ffffffff
amomin.w
635ba926
ae816e00
ae816e00
ae816e00
ae816e00
ae816e00
823197c7
823197c7
823197c7
823197c7
amomax.w
8eb3b723
1615faf1
4c071f6e
4c071f6e
4c071f6e
4c071f6e
4c071f6e
6ef800f5
6ef800f5
6ef800f5
amominu.w
47468144
47468144
47468144
47468144
47468144
33d42566
33d42566
2f907634
121c988e
121c988e
amomaxu.w
b419e62d
b419e62d
b419e62d
b419e62d
b419e62d
b419e62d
b419e62d
b419e62d
e2786c03
e2786c03
amoswap.w
128b6e31
564b1d69
40e8ea53
bb14bcc5
9ce4e4ba
c6c20ac2
00ab8bd8
3dd1e8f5
904d0f98
ddd04031
amoadd.w
84c56c83
671888e4
7111d43c
1ee2c3e5
deca94a4
d488d7af
3d8acb16
dac12031
2ee8821d
d8572f25
amoxor.w
ce40db9b
601992f4
eb77435b
4af6cef0
ec9267ff
fa7bbd8f
5df313d5
f90f0395
2b53fbc9
1b552d8d
amoand.w
30040944
10000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
amoor.w
b839d3c6
bbbffbd6
bffffff7
ffffffff
ffffffff
ffffffff
ffffffff
ffffffff
ffffffff
ffffffff
amomin.w
38e9b9b9
383e8e1b
383e8e1b
cadc0e7d
cadc0e7d
cadc0e7d
b2e62bea
a4af5dc8
a4af5dc8
a4af5dc8
amomax.w
e56f7d0b
e56f7d0b
1937ae25
1937ae25
646f35d7
646f35d7
646f35d7
646f35d7
646f35d7
646f35d7
amominu.w
6b233174
6b233174
222cfe19
222cfe19
17cc620e
17cc620e
17cc620e
17cc620e
17cc620e
17cc620e
amomaxu.w
9faf4aca
d973d97e
d973d97e
d973d97e
d973d97e
d973d97e
d973d97e
d973d97e
d973d97e
eab2dc1e
amoswap.w
da239339
34b8fe13
0343eb99
de10c7f8
c94d8d84
c36ef940
5168228a
47fa74ef
2c474ab9
85a94fd9
amoadd.w
1a543f30
c42a0963
104e9e6a
39ca982a
580d4ea0
25acc70e
72969ff9
f7285c0b
50338dd1
51f37dd0
amoxor.w
ed5c8aef
1ca2e9e1
708d16cd
64a6a820
9650ff75
8282b64e
f1f048e0
df941d20
098548d1
59a6bff4
amoand.w
072bfb80
020b4200
00010200
00000000
00000000
00000000
00000000
00000000
00000000
00000000
amoor.w
4ffb6461
4ffb7f71
7ffb7ff9
fffb7fff
ffff7fff
ffffffff
ffffffff
ffffffff
ffffffff
ffffffff
amomin.w
f65a7786
f65a7786
eaca5748
eaca5748
95ea0fae
87339d39
87339d39
87339d39
87339d39
816e3c6a
amomax.w
4e7f83bd
62e85697
62e85697
62e85697
62e85697
62e85697
62e85697
62e85697
62e85697
62e85697
amominu.w
1e849d2f
1e849d2f
1cb3f3b7
1cb3f3b7
1cb3f3b7
1b625b7a
131b47c0
131b47c0
131b47c0
131b47c0
amomaxu.w
e875e186
e875e186
e875e186
e875e186
e875e186
e875e186
e875e186
e875e186
e875e186
e875e186
amoswap.w
ddb980f5
8043be52
1d80bcf6
72a82e95
201311ea
2527f7ad
c5ef5862
92775fc7
fbf37153
c4587c98
amoadd.w
ae86c765
13cdce01
4661c59e
f7de8a01
829b83c2
c288fec3
e7ae0190
875d201d
eb482bff
d273d71a
amoxor.w
23e49955
aa22b010
274090e6
905199bc
8c208989
2237c3f6
583b36a8
446053c2
97830bd9
2cc105d0
amoand.w
db223284
51022204
41022200
01022200
00002000
00002000
00002000
00002000
00002000
00002000
amoor.w
e1ead00c
e5eadf9d
fdeaffff
fdebffff
ffffffff
ffffffff
ffffffff
ffffffff
ffffffff
ffffffff
amomin.w
7354cae9
f0e3c4b0
f0e3c4b0
f0e3c4b0
f0e3c4b0
f0e3c4b0
f0e3c4b0
f0e3c4b0
f0e3c4b0
f0e3c4b0
amomax.w
5669c186
5669c186
5669c186
5669c186
7430c5c0
7430c5c0
7430c5c0
7430c5c0
7430c5c0
7430c5c0
amominu.w
5b5c5870
003a7123
003a7123
003a7123
003a7123
003a7123
003a7123
003a7123
003a7123
003a7123
amomaxu.w
0faca88b
8d5a8013
bf70b037
bf70b037
bf70b037
bf70b037
bf70b037
bf70b037
bf70b037
bf70b037
amoswap.w
1e35a962
64bea04e
9b75f285
4a866a37
c68bba34
05b3ea23
00cb40c6
bf32403b
803ca49b
ea76a110
amoadd.w
9cc7e65e
43907caa
b67d1597
a0ceed90
20a14652
36ffdbb0
ba97b0dc
57c1db3d
453f3503
55d6cd25
amoxor.w
bd672ae5
cfac19fb
3ccbcf8f
2129c1d6
c3eb5893
c93906a9
30eab213
2cdc331e
e41cfb1a
d00ef07e
amoand.w
32552e8f
22400684
00400480
00400080
00000000
00000000
00000000
00000000
00000000
00000000
amoor.w
181995c1
fadd9fed
ffffbfef
ffffffef
ffffffff
ffffffff
ffffffff
ffffffff
ffffffff
ffffffff
amomin.w
c08840b3
c08840b3
90413a30
90413a30
90413a30
90413a30
90413a30
90413a30
90413a30
90413a30
amomax.w
0d8ec23e
4ce5fec4
4ce5fec4
4ce5fec4
4ce5fec4
4ce5fec4
4ce5fec4
4ce5fec4
4ce5fec4
4ce5fec4
amominu.w
abc1fa54
4ba61e8b
4ba61e8b
4ba61e8b
4ba61e8b
4ba61e8b
4ba61e8b
485b2fd0
485b2fd0
116b717e
amomaxu.w
b500b08b
b500b08b
b500b08b
b500b08b
b500b08b
f4b363b0
f4b363b0
f4b363b0
f4b363b0
f4b363b0
amoswap.w
978bf98e
ebb908d3
db05f72c
6f1ad0a1
c913d1b7
590760d8
bc2418f4
973cae1b
00705eff
8dd72a2e
amoadd.w
606c0eb5
3f8caa84
8201b488
eeddc9b1
b5d3166b
4434a11f
cdbbba29
a08ffc70
a2284827
c1765128
amoxor.w
0bd64714
a9cee773
06a03ce1
6c708d29
1d418b87
534b759a
9eb78c8c
4a345a04
2e68e256
48558b30
amoand.w
fd4b5b4b
30410b0b
30400a01
10400201
00000200
00000000
00000000
00000000
00000000
00000000
amoor.w
75eab0e4
f5fabaf5
fdffbfff
fdffffff
fdffffff
fdffffff
ffffffff
ffffffff
ffffffff
ffffffff
amomin.w
45ce04df
90dbb42e
858f9e1c
858f9e1c
858f9e1c
858f9e1c
858f9e1c
858f9e1c
858f9e1c
858f9e1c
amomax.w
67bd502d
67bd502d
67bd502d
67bd502d
67bd502d
67bd502d
67bd502d
67bd502d
67bd502d
67bd502d
amominu.w
0486d0bd
0486d0bd
0486d0bd
0486d0bd
0486d0bd
0486d0bd
0486d0bd
0486d0bd
0486d0bd
0486d0bd
amomaxu.w
335ebc8f
d3a86843
d3a86843
e5a2c9c9
e5a2c9c9
e5a2c9c9
e5a2c9c9
e5a2c9c9
e5a2c9c9
e5a2c9c9
amoswap.w
b67df848
e376adb9
23bfaef2
0e313674
3970a16c
69b44fc1
0c776577
3ac7955e
2d8182f8
84d1fb4e
amoadd.w
0332c4fd
7179aa2c
26a60d9a
f8100f3b
3df199a6
5945d20d
6c9cfbcb
851e7658
1617bdde
9307bf73
amoxor.w
2d9702a1
0eabd470
1ba993f2
0a0cfdc2
139db066
30dd40d4
4441e95e
c855c46c
dd95b555
54eff295
amoand.w
7da5eea8
45810a08
01000808
01000808
00000808
00000808
00000808
00000008
00000008
00000000
amoor.w
97744dfd
df7e6fff
ffffffff
ffffffff
ffffffff
ffffffff
ffffffff
ffffffff
ffffffff
ffffffff
amomin.w
81b68d5c
81b68d5c
81b68d5c
81b68d5c
81b68d5c
81b68d5c
81b68d5c
81b68d5c
81b68d5c
81b68d5c
amomax.w
a7c3abd9
f43bbd75
f43bbd75
70bcfe34
70bcfe34
70bcfe34
70bcfe34
70bcfe34
70bcfe34
70bcfe34
amominu.w
2fd69078
11792787
11792787
11792787
11792787
11792787
11792787
11792787
11792787
11792787
amomaxu.w
584c97f3
584c97f3
f0167d2e
f0167d2e
f0167d2e
f0167d2e
f0167d2e
f0167d2e
f0167d2e
f0167d2e

*******************************************************************************/
